package com.ruoyi.activiti.listener;

import com.alibaba.fastjson.JSON;
import com.ruoyi.activiti.bpmnparse.x6translator.X6Helper;
import com.ruoyi.activiti.domain.WlnProcessTask;
import com.ruoyi.activiti.mapper.WlnProcessTaskMapper;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.delegate.event.ActivitiEvent;
import org.activiti.engine.delegate.event.ActivitiEventListener;
import org.activiti.engine.delegate.event.impl.ActivitiEntityEventImpl;
import org.activiti.engine.impl.persistence.entity.TaskEntityImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.xml.ws.Response;
import java.util.HashMap;
import java.util.Map;

/**
 * 任务被分配事件监听器 demo
 * @author 一只闲鹿
 */
@Slf4j
@Component
public class TaskAssignedEventListener implements ActivitiEventListener {
    @Autowired
    private X6Helper x6Helper;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private WlnProcessTaskMapper wlnProcessTaskMapper;

    @Override
    public void onEvent(ActivitiEvent activitiEvent) {
        switch (activitiEvent.getType()) {
            case TASK_CREATED:
                if(activitiEvent instanceof ActivitiEntityEventImpl) {
                    ActivitiEntityEventImpl eventImpl = (ActivitiEntityEventImpl) activitiEvent;
                    TaskEntityImpl taskEntity = (TaskEntityImpl) eventImpl.getEntity();
                    log.debug("全局监听创建任务 id {},name {},task key {}",taskEntity.getId(),taskEntity.getName(),taskEntity.getTaskDefinitionKey());
                    log.debug("流程定义id {}",activitiEvent.getProcessDefinitionId());
                    sendTask(activitiEvent,taskEntity,"0");
                }
                break;
            case TASK_COMPLETED:
                if(activitiEvent instanceof ActivitiEntityEventImpl) {
                    ActivitiEntityEventImpl eventImpl = (ActivitiEntityEventImpl) activitiEvent;
                    TaskEntityImpl taskEntity = (TaskEntityImpl) eventImpl.getEntity();
                    log.debug("全局监听完成任务 id {},name {}",taskEntity.getId(),taskEntity.getName());
                    sendTask(activitiEvent,taskEntity,"1");
                }
                break;
            case ENTITY_DELETED:
                // 任务每次完成后，都会发送这个对象删除事件，Attachment, Comment, Deployment, Execution, Group, IdentityLink, Job, Model, ProcessDefinition, ProcessInstance, Task, User.
                // 这些对象都会发起对象删除事件，这里只关注Task。所以对于任务完成会发送两个事件TASK_COMPLETE和ENTITY_DELETE，对于业务系统要能合理处理这两种情况来完成业务中
                // 任务的完成和删除。思路可以如下：业务系统删除任务的时候要检查任务的状态，如果任务是待处理可以直接删除，如果任务是已审批则忽略。为什么要这样？
                // 因为对于会签任务可能出现任务没有审批就被删除了，就是要把待处理的任务删除。但是对于已处理的任务不能删除。
                log.debug("entity_delete {}",JSON.toJSONString(activitiEvent));
                if(activitiEvent instanceof ActivitiEntityEventImpl) {
                    ActivitiEntityEventImpl eventImpl = (ActivitiEntityEventImpl) activitiEvent;
                    if(eventImpl.getEntity() instanceof  TaskEntityImpl) {
                        TaskEntityImpl taskEntity = (TaskEntityImpl) eventImpl.getEntity();
                        // taskType为2，表示要删除该任务
                        sendTask(activitiEvent,taskEntity,"2");
                    }
                }
                break;
        }
    }
    private void sendTask(ActivitiEvent activitiEvent,TaskEntityImpl task,String taskType) {
        // 处理流程中心任务的业务服务后台接口地址，用来在业务系统中添加待办，已办，删除任务等操作。
        String postUrl = (String) x6Helper.getValueByDataKey(activitiEvent.getProcessDefinitionId(),
                task.getTaskDefinitionKey(),
                "postUrl");
        // 配置的点击任务的时候跳转的前端url地址
        String opsUrl = (String) x6Helper.getValueByDataKey(activitiEvent.getProcessDefinitionId(),
                task.getTaskDefinitionKey(),
                "opsUrl");
        if(StringUtils.isEmpty(postUrl)) {
            return;
        }
        Map<String,Object> params = (Map<String, Object>) task.getVariable("data");
        opsUrl = opsUrl + "&instanceId="+task.getProcessInstanceId()+"&taskId="+task.getId()+"&taskType="+taskType+"&taskKey=" +
                task.getTaskDefinitionKey()+"&processDefId="+task.getProcessDefinitionId();
        if(params == null) {
            params = new HashMap<>();
        }
        params.put("url",opsUrl);
        params.put("assignee",task.getAssignee());
        String createDate = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,task.getCreateTime());
        params.put("createTime",createDate);
        params.put("taskName",task.getName());
        params.put("taskDefKey",task.getTaskDefinitionKey());
        params.put("dueDate",task.getDueDate());
        params.put("taskId",task.getId());
        params.put("instanceId",task.getProcessInstanceId());
        params.put("procDefId",task.getProcessDefinitionId());
        params.put("taskType",taskType);
        // 保存任务对象
        saveOrUpdateTask(taskType,opsUrl,postUrl,task);
        // 发送任务给业务系统
        ResponseEntity<String> result = restTemplate.postForEntity(postUrl,params, String.class);
        String body = result.getBody();
        // TODO: 发送成功更新状态为成功，发送失败更新状态为失败。
        log.debug("body {}",body);
    }
    private void saveOrUpdateTask(String taskType,String opsUrl,String postUrl,TaskEntityImpl task){
        if(taskType.equals("0")) {
            WlnProcessTask processTask = new WlnProcessTask();
            processTask.setAssignee(task.getAssignee());
            processTask.setTaskCreateTime(task.getCreateTime());
            processTask.setTaskKey(task.getTaskDefinitionKey());
            processTask.setTaskName(task.getName());
            processTask.setTaskType(taskType);
            processTask.setInstanceId(task.getProcessInstanceId());
            processTask.setProcDefKey(task.getProcessDefinitionId());
            processTask.setUrl(opsUrl);
            processTask.setPostUrl(postUrl);
            processTask.setTaskId(task.getId());
            // 发送中
            processTask.setPushStatus("0");
            wlnProcessTaskMapper.insert(processTask);
        } else if(taskType.equals("1")) {
            WlnProcessTask processTask = new WlnProcessTask();
            processTask.setInstanceId(task.getProcessInstanceId());
            processTask.setTaskId(task.getId());
            processTask.setTaskType(taskType);
            processTask.setUrl(opsUrl);
            processTask.setAssignee(task.getAssignee());
            processTask.setTaskCreateTime(task.getCreateTime());
            wlnProcessTaskMapper.updateTask(processTask);
        } else if(taskType.equals("2")) {
            WlnProcessTask processTask = new WlnProcessTask();
            processTask.setInstanceId(task.getProcessInstanceId());
            processTask.setTaskId(task.getId());
            wlnProcessTaskMapper.deleteTask(processTask);
        }
    }
    @Override
    public boolean isFailOnException() {
        return false;
    }
}
